﻿namespace TriangleGames.TrainResEditor
{
    using System;
    using UnityEditor;
    using UnityEngine;

    public class ErrorSelector : EditorWindow
    {
        [SerializeField]
        private bool filterByFsm;
        private Vector2 scrollPosition;
        private FsmError selectedError;

        private static void DoBottomPanel()
        {
            FsmEditorGUILayout.Divider(new GUILayoutOption[0]);
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            GUILayout.Label("安装错误: " + FsmErrorChecker.CountSetupErrors(), new GUILayoutOption[0]);
            GUILayout.Space(20f);
            GUILayout.Label("运行错误: " + FsmErrorChecker.CountRuntimeErrors(), new GUILayoutOption[0]);
            GUILayout.FlexibleSpace();
            GUILayout.Label("总共: " + FsmErrorChecker.CountAllErrors(), new GUILayoutOption[0]);
            GUILayout.EndHorizontal();
        }

        private void DoErrorHierarchyGUI()
        {
            this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, new GUILayoutOption[0]);
            GUILayout.BeginVertical(new GUILayoutOption[0]);
            foreach (FsmError error in FsmErrorChecker.GetErrors())
            {
                if (!this.filterByFsm || (error.Fsm == FsmEditor.SelectedFsm))
                {
                    GUIStyle actionItem = FsmEditorStyles.ActionItem;
                    if (this.selectedError == error)
                    {
                        actionItem = FsmEditorStyles.ActionItemSelected;
                    }
                    FsmEditorGUILayout.LightDivider(new GUILayoutOption[0]);
                    if (GUILayout.Button(error.ToString(), actionItem, new GUILayoutOption[0]) || GUILayout.Button(error.ErrorString, actionItem, new GUILayoutOption[0]))
                    {
                        this.selectedError = error;
                        GotoError(this.selectedError);
                    }
                }
            }
            GUILayout.EndVertical();
            EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link);
            GUILayout.EndScrollView();
        }

        private void DoToolbar()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, new GUILayoutOption[0]);
            if (GUILayout.Button("刷新", EditorStyles.toolbarButton, new GUILayoutOption[0]))
            {
                FsmErrorChecker.Refresh();
            }
            GUILayout.FlexibleSpace();
            this.filterByFsm = GUILayout.Toggle(this.filterByFsm, new GUIContent("已选择状态机", "只显示已选择状态机的错误."), EditorStyles.toolbarButton, new GUILayoutOption[0]);
            GUILayout.Space(5f);
            if (FsmEditorGUILayout.ToolbarSettingsButton())
            {
                GenerateSettingsMenu().ShowAsContext();
            }
            GUILayout.Space(-5f);
            EditorGUILayout.EndHorizontal();
        }

        private static GenericMenu GenerateSettingsMenu()
        {
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("打开实时错误检查器"), FsmEditorSettings.EnableRealtimeErrorChecker, new GenericMenu.MenuFunction(ErrorSelector.ToggleEnableRealtimeErrorChecker));
            menu.AddItem(new GUIContent("运行时关闭错误检查器"), FsmEditorSettings.DisableErrorCheckerWhenPlaying, new GenericMenu.MenuFunction(ErrorSelector.ToggleDisableErrorCheckerWhenPlaying));
            menu.AddSeparator("");
            menu.AddItem(new GUIContent("检查所需组件"), FsmEditorSettings.CheckForRequiredComponent, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForRequiredComponent));
            menu.AddItem(new GUIContent("检查所需动作字段"), FsmEditorSettings.CheckForRequiredField, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForRequiredField));
            menu.AddItem(new GUIContent("检查未被状态机使用的事件"), FsmEditorSettings.CheckForEventNotUsed, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForEventNotUsed));
            menu.AddItem(new GUIContent("检查遗漏事件的过渡"), FsmEditorSettings.CheckForTransitionMissingEvent, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForTransitionMissingEvent));
            menu.AddItem(new GUIContent("检查确实目标的过渡 "), FsmEditorSettings.CheckForTransitionMissingTarget, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForTransitionMissingTarget));
            menu.AddItem(new GUIContent("检查重复过渡"), FsmEditorSettings.CheckForDuplicateTransitionEvent, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForDuplicateTransitionEvent));
            menu.AddItem(new GUIContent("检查鼠标事件设置错误"), FsmEditorSettings.CheckForMouseEventErrors, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForMouseEventErrors));
            menu.AddItem(new GUIContent("检查碰撞事件设置错误"), FsmEditorSettings.CheckForCollisionEventErrors, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForCollisionEventErrors));
            menu.AddItem(new GUIContent("检查约束预制件"), FsmEditorSettings.CheckForPrefabRestrictions, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForPrefabRestrictions));
            menu.AddItem(new GUIContent("检查过期动作"), FsmEditorSettings.CheckForObsoleteActions, new GenericMenu.MenuFunction(ErrorSelector.ToggleCheckForObsoleteActions));
            return menu;
        }

        private static void GotoError(FsmError error)
        {
            if ((error != null) && (error.Fsm != null))
            {
                FsmEditor.SelectFsm(error.Fsm);
                if (error.State != null)
                {
                    FsmEditor.SelectState(error.State, true);
                    if (error.Action != null)
                    {
                        FsmEditor.SelectAction(error.Action, true);
                        FsmEditor.Repaint(true);
                    }
                }
            }
        }

        private void OnEnable()
        {
            base.title = "错误检查";
            base.minSize = new Vector2(200f, 100f);
            base.autoRepaintOnSceneChange = true;
        }

        private void OnGUI()
        {
            if (FsmEditor.Instance == null)
            {
                base.Close();
            }
            else
            {
                if (EditorApplication.isCompiling)
                {
                    GUI.enabled = false;
                }
                if (!FsmEditorStyles.IsInitialized())
                {
                    FsmEditorStyles.Init();
                }
                this.DoToolbar();
                this.DoErrorHierarchyGUI();
                DoBottomPanel();
            }
        }

        private static void ToggleCheckForCollisionEventErrors()
        {
            FsmEditorSettings.CheckForCollisionEventErrors = !FsmEditorSettings.CheckForCollisionEventErrors;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForDuplicateTransitionEvent()
        {
            FsmEditorSettings.CheckForDuplicateTransitionEvent = !FsmEditorSettings.CheckForDuplicateTransitionEvent;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForEventNotUsed()
        {
            FsmEditorSettings.CheckForEventNotUsed = !FsmEditorSettings.CheckForEventNotUsed;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForMouseEventErrors()
        {
            FsmEditorSettings.CheckForMouseEventErrors = !FsmEditorSettings.CheckForMouseEventErrors;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForObsoleteActions()
        {
            FsmEditorSettings.CheckForObsoleteActions = !FsmEditorSettings.CheckForObsoleteActions;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForPrefabRestrictions()
        {
            FsmEditorSettings.CheckForPrefabRestrictions = !FsmEditorSettings.CheckForPrefabRestrictions;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForRequiredComponent()
        {
            FsmEditorSettings.CheckForRequiredComponent = !FsmEditorSettings.CheckForRequiredComponent;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForRequiredField()
        {
            FsmEditorSettings.CheckForRequiredField = !FsmEditorSettings.CheckForRequiredField;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForTransitionMissingEvent()
        {
            FsmEditorSettings.CheckForTransitionMissingEvent = !FsmEditorSettings.CheckForTransitionMissingEvent;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleCheckForTransitionMissingTarget()
        {
            FsmEditorSettings.CheckForTransitionMissingTarget = !FsmEditorSettings.CheckForTransitionMissingTarget;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleDisableErrorCheckerWhenPlaying()
        {
            FsmEditorSettings.DisableErrorCheckerWhenPlaying = !FsmEditorSettings.DisableErrorCheckerWhenPlaying;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }

        private static void ToggleEnableRealtimeErrorChecker()
        {
            FsmEditorSettings.EnableRealtimeErrorChecker = !FsmEditorSettings.EnableRealtimeErrorChecker;
            FsmEditorSettings.SaveSettings();
            FsmErrorChecker.Refresh();
        }
    }
}

